chore: prune dead code, tighten typing, add (method, path) parity test#3
Merged
Merged
Conversation
Replace Python preprocess_spec.py with call to shared Node.js CLI tool. Fixes missing setRequiredOnAllOfMembers and flattenCircularOneOf steps, and removes divergent _REQUEST_PREFIXES exemption logic. Made-with: Cursor
Every resource method that accepts a body now validates it through the Pydantic model before sending. Raw dicts are rejected in _serialize_body to prevent bypassing validation. Dicts can still be used by passing them through validate_request() first. Made-with: Cursor
Made-with: Cursor
- Replace all Any return/param types in _http.py with concrete types (END-1078) - Remove dead unwrap_single function - Add 31 descriptive enum aliases in types.py (END-1079) - Re-export all enum aliases from __init__.py for stable public API Made-with: Cursor
Resolves END-1162.
Resource method signatures previously accepted only the typed Pydantic
model (e.g. CreateMonitorRequest), but the runtime ``validate_request``
helper coerces dicts via ``model_validate`` and the README/client
docstrings show dict-style usage. Under ``mypy --strict`` those examples
were type errors.
Introduce ``RequestBody[T] = T | Mapping[str, Any]`` in ``_validation``
and apply it to every mutating resource method body parameter so dict
literals type-check while typed model instances remain a first-class
option. Re-export ``RequestBody`` and the previously omitted
``AddIncidentUpdateRequest`` from the package root and ``types`` module.
Add ``tests/test_spec_parity.py`` to lock the SDK against logical drift
from ``docs/openapi/monitoring-api.json``:
* every public DTO must exist in the spec (catches removals/renames),
* every request DTO's required fields must be a superset of the spec's,
* every mutating method body annotation must include ``Mapping[str, Any]``
(catches future regressions to the dict ergonomics fix), and
* every top-level path the SDK calls must exist in the spec.
All 681 tests pass; ``mypy --strict src/`` is clean; manual smoke check
confirms dict-style ``client.monitors.create({...})`` now type-checks.
Made-with: Cursor
- END-1082 Remove dead unwrap_single helper and stop generating the
unused CursorPage model (the API now returns concrete cursor pages
per resource so the generic was unreachable). Regenerate _generated.py
from the refreshed vendored spec.
- _http.py / _pagination.py: tighten typing — explicit dict[str, Any]
annotations, drop the implicit Any return paths flagged by mypy.
- Mirror the SDK-JS spec-paths test in tests/test_spec_parity.py with
a (method, path) check for every resource the SDK calls. Same fix
applied: incidents.delete() (non-existent endpoint) is removed; the
rest of the table now lines up with the OpenAPI spec.
- Refresh test_negative_validation.py / test_schemas.py to reflect the
optional/nullable fields the API actually emits (ResolveIncidentRequest,
CreateNotificationPolicyRequest, etc.) so previously stale assertions
pass again. Add tests/test_typing.py for shared helpers.
- Refresh docs/openapi/monitoring-api.json to match the new mini spec
(incl. /api/v1/alert-channels/{id} GET endpoint).
ruff format --check, ruff check, mypy --strict (src + tests), pytest
(681 tests) all green.
Made-with: Cursor
Updates docs/openapi/monitoring-api.json after the upstream API change that reverted the explicit oneOf annotation on MonitorConfig — the property-level inlined oneOf preserves subtype validation in the generated models. Made-with: Cursor
…details
Picks up the upstream @devhelm/openapi-tools update that inlines
discriminator subtypes and rewrites parents as oneOf+discriminator. The
generated Pydantic models now use:
type: Literal["bearer"] (and "basic", "header", "api_key")
check_type: Literal["http"] (and "tcp", "icmp", "dns", "mcp_server")
with `Annotated[Union[...], Field(discriminator="type")]` on the parent
union (MonitorAuthConfig and CheckTypeDetailsDto). Pydantic's
discriminator-aware union resolution now picks the right subtype in O(1)
on validation, vs the previous "try every member, keep the first that
parses" fallback that misclassified shape-equivalent subtypes (e.g.
BearerAuthConfig vs BasicAuthConfig — both `{vault_secret_id}` only).
Spec refresh also propagates the regular field-level fixes from the
upstream typing audit. ruff, mypy strict, and pytest (681 tests) pass.
Made-with: Cursor
Surface the typed request model so downstream surfaces (MCP server, tests) can import it from `devhelm.types` directly instead of reaching into `devhelm._generated`. Made-with: Cursor
Regenerate the Pydantic models against the updated OpenAPI spec. The mono-side preprocessor now inlines nullable references to deduction- based polymorphic parents, so `UpdateMonitorRequest.config` resolves to a proper `DnsMonitorConfig | HttpMonitorConfig | ... | None` union instead of a vacuous reference to the empty `MonitorConfig` base. No source changes; generated code only. Made-with: Cursor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
unwrap_singlehelper and stop generating the unusedCursorPagemodel (the API now returns concrete cursor pages per resource so the generic was unreachable)._http.py/_pagination.py: tighten typing — explicitdict[str, Any]annotations, drop the implicit-Any return paths flagged by mypy strict.tests/test_spec_parity.pywith a(method, path)check for every resource the SDK calls. Same fix applied:incidents.delete()(non-existent endpoint) is removed; the rest of the table now lines up with the OpenAPI spec.test_negative_validation.py/test_schemas.pyto reflect the optional/nullable fields the API actually emits (ResolveIncidentRequest,CreateNotificationPolicyRequest, etc.) so previously stale assertions pass again. Newtests/test_typing.pycovers shared helpers.docs/openapi/monitoring-api.jsonto match the new mini spec (incl. the new/api/v1/alert-channels/{id}GET endpoint)._generated.pyfrom the refreshed spec.Test plan
uv run --frozen ruff format --checkuv run --frozen ruff checkuv run --frozen mypy src tests(strict)uv run --frozen pytest -q(681 tests pass)mono#246runsmake test-surface SURFACE=sdk-pythonagainst this branch)Made with Cursor